package com.wu.family.utils.ze;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;

public class LoadAvatarBmpMgr {
	public final static String PIC_CACHE_PATH = Environment.getExternalStorageDirectory() 
			+ "/family/.avatarTemp/";
	private static LoadAvatarBmpMgr instance = null;
	private ExecutorService executorService = Executors.newFixedThreadPool(5);
	public Map<String, WeakReference<Bitmap>> imageCache = new HashMap<String, WeakReference<Bitmap>>();
	
	private LoadAvatarBmpMgr() {
		File dir = new File(PIC_CACHE_PATH);
		if ( !dir.exists()) {
			dir.mkdirs();
		}
	}
	
	public static LoadAvatarBmpMgr getInstance() {
		if (instance == null) {
			instance = new LoadAvatarBmpMgr();
		}
		return instance;
	}
	 
	public void addImageCache(Bitmap bitmap, String imageUrl) {
		FileOutputStream outputStream = null;
		ObjectOutputStream	objectOutputStream = null ;
		try {
			if(bitmap != null)
			{
				imageCache.put(imageUrl, new WeakReference<Bitmap>(bitmap));
				File drawableFile = new File(PIC_CACHE_PATH + formatString( imageUrl ));
				if (drawableFile.exists()) {
					drawableFile.delete();
				}
				drawableFile.createNewFile();
				outputStream = new FileOutputStream(drawableFile);
				objectOutputStream = new ObjectOutputStream(outputStream);
				objectOutputStream.writeObject( bitmap2ByteArray(bitmap) );
			
				objectOutputStream.flush();
				objectOutputStream.close();
				outputStream.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void removeImageCache(String urlString) {
		try {
			if (imageCache.containsKey(urlString)) {
				imageCache.remove(urlString);
			}
			File cacheFile = new File( PIC_CACHE_PATH + formatString( urlString ) );
			if ( cacheFile.exists() ) {
				cacheFile.delete();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void deleteSDcardCache() {
		File dir = new File(PIC_CACHE_PATH);
		if (dir.exists()) {
			File[] Files = dir.listFiles();
			if (Files != null && Files.length > 0) {
				for (File file : Files) {
					file.delete();
				}
			}
		}
		imageCache.clear();
	}
	
	public Bitmap loadBitmap(final String imageUrl, final ImageView view ,ImageCallBack customCallBack) {
		final ImageCallBack callBack;
		if (customCallBack != null) {
			callBack = customCallBack;
		}else {
			callBack = defaultCallBack;
		}
		final Handler  handler =  new Handler() {
			public void handleMessage(Message msg) {
				if( msg.what == 0 )
				{
					callBack.setImage((Bitmap) msg.obj, imageUrl, view);
				}else if( msg.what == 1 )
				{
					if ( msg.obj == null ) {
						netLoadImage(imageUrl, this);
					}else
					{
						callBack.setImage((Bitmap) msg.obj, imageUrl, view);
					}
				}
				
			}; 
		 };
		 
		view.setTag(imageUrl);
		Bitmap bitmap = null;
		 if (imageCache.containsKey(imageUrl)) {
	            WeakReference<Bitmap> softReference = imageCache.get(imageUrl);
	            bitmap = softReference != null ? softReference.get() : null;
	            if ( null == bitmap ) {
	            	imageCache.remove(imageUrl);
	            	loadBitmap(imageUrl,view,callBack);
				}else {
					callBack.setImage(bitmap, imageUrl, view);
		            return bitmap;
				}
		 }else {
			 findLocalImage(imageUrl, handler); 
		 }
		callBack.setImage(bitmap, imageUrl, view);
		return null;
	}
	
	public void findLocalImage(final String imageUrl,final Handler handler) {
		executorService.submit(new Runnable() {
			@Override
			public void run() {
				Bitmap bitmap = null;
				FileInputStream inputStream = null;
				ObjectInputStream objectInputStream = null;
				try {
					File cacheFile = new File( PIC_CACHE_PATH + formatString( imageUrl ) );
					if ( cacheFile.exists() ) {
						inputStream = new FileInputStream(cacheFile);
						objectInputStream = new ObjectInputStream(inputStream);
						byte[] buffer = (byte[]) objectInputStream.readObject();
						bitmap = ByteArray2Bitmap( buffer);
					}
					if(bitmap != null) {
						imageCache.put(imageUrl, new WeakReference<Bitmap>(bitmap));
					}
					handler.sendMessage(handler.obtainMessage(1, bitmap));
					
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					try {
						if (inputStream != null ) {
							inputStream.close();
							inputStream = null;
						}
						if (objectInputStream != null ) {
							objectInputStream.close();
							objectInputStream = null;
						}
					} catch (Exception e2) {
					}
				}
			}
		});
	}
	
	public void netLoadImage(final String imageUrl,final Handler handler) {
		executorService.submit(new Runnable() {
			@Override
			public void run() {
				Bitmap bitmap = null;
				FileOutputStream outputStream = null;
				ObjectOutputStream	objectOutputStream = null ;
				Log.i("Avatar NoCache", imageUrl);
				try {
					HttpURLConnection conn = (HttpURLConnection)new URL(imageUrl).openConnection();
					conn.setConnectTimeout(5 * 1000); 
					conn.setRequestMethod("GET");
					if(conn.getResponseCode()==200){
						BitmapFactory.Options options = new BitmapFactory.Options(); 
						options.inJustDecodeBounds = false;
						options.inPreferredConfig = Bitmap.Config.RGB_565;
						options.inPurgeable = true;
						options.inInputShareable = true;
						
						BufferedInputStream buf = new BufferedInputStream(conn.getInputStream());
						bitmap = BitmapFactory.decodeStream(buf, null, options);
					}
					if(bitmap != null) {
						imageCache.put(imageUrl, new WeakReference<Bitmap>(bitmap));
						
						handler.sendMessage(handler.obtainMessage(0, bitmap));
						File bitmapFile = new File(PIC_CACHE_PATH + formatString( imageUrl ));
						if (bitmapFile.exists()) { 
							bitmapFile.delete();
						}
						bitmapFile.createNewFile();
						outputStream = new FileOutputStream(bitmapFile);
						objectOutputStream = new ObjectOutputStream(outputStream);
						objectOutputStream.writeObject( bitmap2ByteArray(bitmap) );
					
						objectOutputStream.flush();
						objectOutputStream.close();
						outputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			
			}
		});
	}
	
	public byte[] bitmap2ByteArray(final Bitmap bitmap) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bitmap.compress(CompressFormat.JPEG, 100, baos);
		byte[] drawableArray = baos.toByteArray();
		try {
			baos.close();
			baos = null;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return drawableArray;
	}
	
	public Bitmap ByteArray2Bitmap(byte[] drawableArray) {
		Bitmap bitmap = BitmapFactory.decodeByteArray(drawableArray, 0, drawableArray.length);
		return bitmap;
	}
	
	public ImageCallBack defaultCallBack = new ImageCallBack() {
		@Override 
		public void setImage(Bitmap bitmap, String url, ImageView view) {
			if( url.equals((String)view.getTag())) {
				view.setImageBitmap(bitmap);
			}
		}
	};
	
	public String formatString( final String from ) {
		//return MD5.MD5Encode(from)+ ((from.lastIndexOf(".")!=-1)?from.substring(from.lastIndexOf(".")):".jpg");
		String formatString = new String(from);
		String[] strs = formatString.split("/");
		formatString = "";
		for( int i=0; i<strs.length; i++ ) {
			formatString = formatString + strs[i];
		}
		formatString = formatString.substring(formatString.lastIndexOf("com"));
		formatString = formatString.contains("!")?formatString:(formatString+"!600");
		
		return formatString;
	}
	
	public interface ImageCallBack {
		public void setImage(Bitmap bitmap,String url, ImageView view);
	}
}
